package com.watson.ftp.utils;


import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.util.*;


/**
 * @Author watson
 * @Date 2022/6/13 14:23
 * @Description: TODO
 * @Version 1.0
 */

public class SftpUtil {
    private static final Logger log = LoggerFactory.getLogger(SftpUtil.class);
    private String ip = "";
    private String username = "";
    private String password = "";
    private int port = -1;
    private ChannelSftp sftpChannel = null;
    private Session session = null;

    public SftpUtil(String serverIP, int port, String username, String password) {
        this.ip = serverIP;
        this.port = port;
        this.username = username;
        this.password = password;
        log.info("初始化sftp:{},{},{},{}", new Object[]{serverIP, port, username, password});
    }

    public SftpUtil(String serverIP, int port, String username) {
        this.ip = serverIP;
        this.port = port;
        this.username = username;
        this.password = this.password;
        log.info("初始化sftp:{},{},{},{}", new Object[]{serverIP, port, username});
    }

    public boolean connectServer() {
        boolean retflag = false;

        try {
            JSch jsch = new JSch();
            this.session = jsch.getSession(this.username, this.ip, this.port);
            if (this.password != null) {
                this.session.setPassword(this.password);
            }

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            this.session.setConfig(config);
            this.session.connect();
            this.sftpChannel = (ChannelSftp) this.session.openChannel("sftp");
            this.sftpChannel.connect();
            retflag = true;
            log.info("sftp:{},{},{},{}连接成功", new Object[]{this.ip, this.port, this.username, this.password});
        } catch (JSchException var4) {
            log.error("连接sftp:{},{}失败,", new Object[]{this.ip, this.username, var4});
        }

        return retflag;
    }

    public boolean connectServer(String filePath, String passphrase) {
        boolean retflag = false;

        try {
            JSch jsch = new JSch();
            jsch.addIdentity(filePath);
            this.session = jsch.getSession(this.username, this.ip, this.port);
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            this.session.setConfig(config);
            if (passphrase != null && !"".equals(passphrase)) {
                UserInfo ui = new SftpUtil.MyUserInfo(passphrase);
                this.session.setUserInfo(ui);
            }

            this.session.connect();
            this.sftpChannel = (ChannelSftp) this.session.openChannel("sftp");
            this.sftpChannel.connect();
            retflag = true;
            log.info("sftp:{},{},{},{}连接成功", new Object[]{this.ip, this.port, this.username, filePath});
        } catch (JSchException var7) {
            log.error("连接sftp:{},{}失败,", new Object[]{this.ip, this.username, var7});
        }

        return retflag;
    }

    public boolean isExists(String directory) {
        boolean retflag = false;

        try {
            this.sftpChannel.cd(directory);
            retflag = true;
        } catch (SftpException var4) {
            log.error("判断目标服务器上文件路径是否存在失败,", var4);
        }

        return retflag;
    }

    public List<String> getFileList(String directory) {
        List<String> fileNames = null;
        if (!this.isExists(directory)) {
            return fileNames;
        } else {
            try {
                Vector<String> files = this.sftpChannel.ls(this.sftpChannel.pwd());
                fileNames = new ArrayList();

                for (int i = 0; i < files.size(); ++i) {
                    Object obj = files.elementAt(i);
                    if (obj instanceof LsEntry) {
                        LsEntry entry = (LsEntry) obj;
                        if (!entry.getAttrs().isDir()) {
                            fileNames.add(entry.getFilename());
                        }
                    }
                }
            } catch (SftpException var7) {
                log.error("获取目标服务器上目录下文件列表失败,", var7);
            }

            return fileNames;
        }
    }

    public boolean mkdirs(String directory) {
        boolean retflag = false;
        if (this.sftpChannel == null) {
            return retflag;
        } else if (directory == null) {
            return retflag;
        } else {
            directory = directory.replace("\\", "/");
            String[] dir = directory.split("/");
            String headpath = "";

            try {
                for (int i = 0; i < dir.length; ++i) {
                    String path = dir[i];
                    if (path != null && !"".equals(path)) {
                        if (!this.isExists(headpath + "/" + path)) {
                            this.sftpChannel.mkdir(headpath + "/" + path);
                        }

                        headpath = headpath + "/" + path;
                    }
                }

                retflag = true;
            } catch (SftpException var7) {
                log.error("远程创建目录失败,", var7);
            }

            return retflag;
        }
    }

    public boolean upload(String remoteDirectory, String localFilePath, String fileNewName) {
        boolean retflag = false;
        if (this.sftpChannel == null) {
            log.error("上传文件{}至目录{}失败，未打开sftp", localFilePath, remoteDirectory);
            return retflag;
        } else {
            FileInputStream fileinputstream = null;

            try {
                this.mkdirs(remoteDirectory);
                this.sftpChannel.cd(remoteDirectory);
                File file = new File(localFilePath);
                if (!file.exists()) {
                    boolean var20 = retflag;
                    return var20;
                }

                fileinputstream = new FileInputStream(file);
                String filename = fileNewName != null && !"".equals(fileNewName) ? fileNewName : file.getName();
                this.sftpChannel.put(fileinputstream, filename);
                retflag = true;
                log.info("上传文件{}至目录{}成功", localFilePath, remoteDirectory);
            } catch (Exception var18) {
                log.error("上传文件{}至目录{}失败", localFilePath, remoteDirectory);
            } finally {
                if (fileinputstream != null) {
                    try {
                        fileinputstream.close();
                    } catch (IOException var17) {
                        log.error("文件流关闭失败,", var17);
                    }
                }

            }

            return retflag;
        }
    }

    public boolean download(String directory, String filename, String saveDir, String saveFileName) {
        boolean retflag = false;
        if (this.sftpChannel == null) {
            return retflag;
        } else {
            FileOutputStream fileinputstream = null;

            try {
                this.sftpChannel.cd(directory);
                String saveFilePath = null;
                if (!saveDir.endsWith("/") && !saveDir.endsWith("\\")) {
                    saveFilePath = saveDir + File.separator + saveFileName;
                } else {
                    saveFilePath = saveDir + saveFileName;
                }

                File file = new File(saveFilePath);
                fileinputstream = new FileOutputStream(file);
                this.sftpChannel.get(filename, fileinputstream);
                retflag = true;
            } catch (SftpException var19) {
                log.error("sftp连接失败,", var19);
            } catch (FileNotFoundException var20) {
                log.error("文件找不到,", var20);
            } finally {
                if (fileinputstream != null) {
                    try {
                        fileinputstream.close();
                    } catch (IOException var18) {
                        log.error("文件流关闭失败,", var18);
                    }
                }

            }

            return retflag;
        }
    }

    private boolean downloadDir(String directory, String filename, String saveDir, String saveFileName) {
        boolean retflag = false;
        if (this.sftpChannel == null) {
            return retflag;
        } else {
            FileOutputStream fileinputstream = null;

            try {
                String saveFilePath = null;
                if (!saveDir.endsWith("/") && !saveDir.endsWith("\\")) {
                    saveFilePath = saveDir + File.separator + saveFileName;
                } else {
                    saveFilePath = saveDir + saveFileName;
                }

                File file = new File(saveFilePath);
                fileinputstream = new FileOutputStream(file);
                this.sftpChannel.get(filename, fileinputstream);
                retflag = true;
            } catch (SftpException var19) {
                log.error("sftp连接失败,", var19);
            } catch (FileNotFoundException var20) {
                log.error("文件找不到,", var20);
            } finally {
                if (fileinputstream != null) {
                    try {
                        fileinputstream.close();
                    } catch (IOException var18) {
                        log.error("文件流关闭失败,", var18);
                    }
                }

            }

            return retflag;
        }
    }

    public boolean downloadDirectory(String directory, String saveDir) {
        boolean result = false;
        List<String> fileNames = this.getFileList(directory);
        if (CollectionUtils.isEmpty(fileNames)) {
            return result;
        } else {
            Iterator var5 = fileNames.iterator();

            while (var5.hasNext()) {
                String fileName = (String) var5.next();
                result = this.downloadDir(directory, fileName, saveDir, fileName);
                if (!result) {
                    result = this.downloadDir(directory, fileName, saveDir, fileName);
                }
            }

            return result;
        }
    }

    public boolean downloadDirectory(String directory, String saveDir, List<String> downFailFileNames) {
        boolean result = false;
        List<String> fileNames = this.getFileList(directory);
        if (CollectionUtils.isEmpty(fileNames)) {
            return result;
        } else {
            Iterator var6 = fileNames.iterator();

            while (var6.hasNext()) {
                String fileName = (String) var6.next();
                result = this.downloadDir(directory, fileName, saveDir, fileName);
                if (!result) {
                    downFailFileNames.add(fileName);
                    result = true;
                }
            }

            return result;
        }
    }

    public void closeServer() {
        if (this.sftpChannel != null) {
            this.sftpChannel.disconnect();
        }

        if (this.session != null) {
            this.session.disconnect();
        }

    }

    public ChannelSftp getSftpChannel() {
        return this.sftpChannel;
    }

    public static void main(String[] args) {
        SftpUtil sft = new SftpUtil("192.168.43.112", 22, "weblogic", "weblogic");
        sft.connectServer();
        sft.download("/home/weblogic/CRQ/tmp/ReportDownload/2015/20151118/", "2015111800000012.html", "d:\\", "2015111800000012.html");
        System.out.println(sft.isExists("/home/weblogic/ddd/ddd/dd/dd/dd/"));
        System.out.println(sft.mkdirs("/home/weblogic/ddd/ddd/dd/dd/dd/"));
        sft.closeServer();
    }

    public static class MyUserInfo implements UserInfo {
        private String passphrase = null;

        public MyUserInfo(String passphrase) {
            this.passphrase = passphrase;
        }

        @Override
        public String getPassphrase() {
            return this.passphrase;
        }

        @Override
        public String getPassword() {
            return null;
        }

        @Override
        public boolean promptPassphrase(String s) {
            return true;
        }

        @Override
        public boolean promptPassword(String s) {
            return true;
        }

        @Override
        public boolean promptYesNo(String s) {
            return true;
        }

        @Override
        public void showMessage(String s) {
            SftpUtil.log.info("sftp登录信息{}", s);
        }
    }
}
